--[[
	Copyright (C) 2006-2007 Nymbia

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
]]
local L = AceLibrary("AceLocale-2.2"):new("Quartz")
local media = LibStub("LibSharedMedia-3.0")

local unpack = unpack

local Quartz = Quartz
if Quartz:HasModule('LatencyMF2') then
	return
end
local QuartzLatencyMF2 = Quartz:NewModule('LatencyMF2', 'AceHook-2.1')
local QuartzPlayer = Quartz:GetModule('Player')
local QuartzLatency = Quartz:GetModule('Latency')
local lagbox, db, timeDiff, sendTime, castBar, alignoutside
local sentSpark

local width
local mindflayname
	
function QuartzLatencyMF2:OnInitialize()
	db = Quartz:AcquireDBNamespace("Latency")
end
function QuartzLatencyMF2:OnEnable()
	mindflayname = (GetSpellInfo(15407)) or "Mind Flay"

	self:Hook(QuartzPlayer, "UNIT_SPELLCAST_START")
	self:Hook(QuartzPlayer, "UNIT_SPELLCAST_CHANNEL_START")
	self:Hook(QuartzPlayer, "UNIT_SPELLCAST_CHANNEL_UPDATE")
	
	self:RegisterEvent("UNIT_SPELLCAST_SENT")
	
	self:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED", "hideIfPlayer")
	media.RegisterCallback(self, "LibSharedMedia_SetGlobal", function(mtype, override)
		if mtype == "statusbar" then
			lagbox:SetTexture(media:Fetch("statusbar", override))
		end
	end)
	if not lagbox then
		castBar = QuartzPlayer.castBar
		lagbox = castBar:CreateTexture(nil, "OVERLAY")
		self.lagbox = lagbox

		sentSpark = castBar:CreateTexture(nil, 'OVERLAY')
		self.sentSpark = sentSpark
	end
	Quartz.ApplySettings()
end
function QuartzLatencyMF2:OnDisable()
	lagbox:Hide()
	sentSpark:Hide()
end
function QuartzLatencyMF2:UNIT_SPELLCAST_SENT(unit)
	if unit ~= 'player' then
		return
	end
	sendTime = GetTime()
	if castBar:IsShown() then
		local left
		if QuartzPlayer.casting or QuartzPlayer.channeling then
			left = select(4,QuartzPlayer.castBarSpark:GetPoint(1))
		end
		if left then
			sentSpark:ClearAllPoints()
			sentSpark:SetPoint('CENTER', castBar, 'LEFT', left, 0)
			sentSpark:Show()
		end
	end
end
function QuartzLatencyMF2:UNIT_SPELLCAST_START(object, unit)
	self.hooks[object].UNIT_SPELLCAST_START(object, unit)
	if unit ~= 'player' or not sendTime then
		return
	end
	lagbox:Hide()
	sentSpark:Hide()
end
function QuartzLatencyMF2:UNIT_SPELLCAST_CHANNEL_START(object, unit)
	self.hooks[object].UNIT_SPELLCAST_CHANNEL_START(object, unit)
	if unit ~= 'player' or not sendTime then
		return
	end
	sentSpark:Hide()
	if db.profile.lagembed then
		return
	end
	if (UnitChannelInfo(unit))~=mindflayname then
		lagbox:Hide()
		return
	end

	local startTime = QuartzPlayer.startTime
	self.originalStartTime = startTime
	local endTime = QuartzPlayer.endTime
	timeDiff = GetTime() - sendTime
	
	local castlength = endTime - startTime
	timeDiff = timeDiff > castlength and castlength or timeDiff
	local perc = timeDiff / castlength
	--Quartz:Print('UNIT_SPELLCAST_CHANNEL_START', startTime, castlength, timeDiff)
	if perc > 1/3 then
		lagbox:Hide()
		return
	end
	
	lagbox:ClearAllPoints()
	lagbox:SetTexCoord(perc,1,0,1)
	lagbox:SetPoint('LEFT', castBar, 'LEFT', width * 1/3, 0)
	lagbox:SetWidth(width * perc)
	lagbox:Show()
end
function QuartzLatencyMF2:UNIT_SPELLCAST_CHANNEL_UPDATE(object, unit)
	self.hooks[object].UNIT_SPELLCAST_CHANNEL_UPDATE(object, unit)
	if unit ~= 'player' or db.profile.lagembed then
		return
	end
	if (UnitChannelInfo(unit))~=mindflayname then
		return
	end
	local startTime = QuartzPlayer.startTime
	local offset = self.originalStartTime - startTime
	if offset==0 then
		return
	else
		-- There's no point in displaying the QuartzLatency lagbox, because the last tick is lost anyways.
		QuartzLatency.lagbox:Hide()
	end

	local castlength = QuartzPlayer.endTime - startTime
	local offsetperc = offset/castlength
	local perc = timeDiff / castlength

	local lagstart2 = 1/3-offsetperc

	lagbox:ClearAllPoints()
	local remaining = GetTime()
	if lagstart2 > 0 then
		--Quartz:Print('pushback1', offset, offsetperc*100, startTime, castlength, timeDiff)
		lagbox:SetPoint('LEFT', castBar, 'LEFT', width * lagstart2, 0)
	else
		--Quartz:Print('pushback2', offset, startTime, castlength, timeDiff)
		local lagend2 = lagstart2 + timeDiff
		lagbox:SetPoint('LEFT', castBar, 'LEFT', 0, 0)
		lagbox:SetWidth(width * lagend2)
	end
	if sentSpark:IsShown() then
		-- Not that important...
		sentSpark:Hide()
	end
end

function QuartzLatencyMF2:hideIfPlayer(unit)
	if unit == 'player' then
		lagbox:Hide()
		sentSpark:Hide()
	end
end

function QuartzLatencyMF2:ApplySettings()
	if lagbox and Quartz:IsModuleActive('LatencyMF2') then
		castBar = QuartzPlayer.castBar
		
		local db = db.profile
		lagbox:SetHeight(castBar:GetHeight())
		lagbox:SetTexture(media:Fetch('statusbar', QuartzPlayer.db.profile.texture))
		lagbox:SetAlpha(db.lagalpha)
		lagbox:SetVertexColor(unpack(db.lagcolor))

		sentSpark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark")
		sentSpark:SetVertexColor(unpack(Quartz.db.profile.sparkcolor))
		sentSpark:SetBlendMode('ADD')
		sentSpark:SetWidth(20)
		sentSpark:SetHeight(QuartzPlayer.db.profile.h*2.2)

		width = QuartzPlayer.db.profile.w

		if db.lagembed then
			lagbox:Hide()
			sentSpark:Hide()
		end
	end
end
